package cc.wanforme.st.server.config;

import java.util.Objects;

import org.springframework.aop.Advisor;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Role;
import org.springframework.security.authorization.method.AuthorizationInterceptorsOrder;
import org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor;

import cc.wanforme.st.server.authen.anno.AuthUtil;
import cc.wanforme.st.server.authen.anno.GenericAuthorizationManager;
import cc.wanforme.st.server.authen.anno.HasPermission;
import cc.wanforme.st.server.authen.anno.HasPermissionAuthorizationManager;
import cc.wanforme.st.server.authen.anno.HasRole;

/**
 * 自定义认证注解配置
 */
@Configuration
//@EnableWebSecurity // 已在 SpringSecurityConfiguration 中开启
//@EnableGlobalMethodSecurity(prePostEnabled=true)
public class AuthAnnotationConfiguration {

	// 创建 @HasPermission 的拦截器
	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	Advisor hasPermissionAuthorizationMethodInterceptor() {
		HasPermissionAuthorizationManager authorizationManager = new HasPermissionAuthorizationManager();
		AuthorizationManagerBeforeMethodInterceptor interceptor = new AuthorizationManagerBeforeMethodInterceptor(
				AuthUtil.forAnnotations(HasPermission.class), authorizationManager);
		// 顺序就和 @PreAuthorize 的顺序保持一致 
		interceptor.setOrder(AuthorizationInterceptorsOrder.PRE_AUTHORIZE.getOrder());
		return interceptor;
	}
	
	// 创建 @HasRole 的拦截器 （创建的方式是 HasPermission 的升级版）
	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	Advisor hasRoleAuthorizationMethodInterceptor() {
		Class<HasRole> clazz = HasRole.class;
		GenericAuthorizationManager<HasRole> authorizationManager = new GenericAuthorizationManager<>(clazz,
				// spring默认对角色的设计就是以 'ROLE_'开头的权限，代码层面上讲，本质还是代表权限的字符串
				(grant,anno) -> Objects.equals(grant.getAuthority(), "ROLE_" + anno.value())); 
		
		AuthorizationManagerBeforeMethodInterceptor interceptor = new AuthorizationManagerBeforeMethodInterceptor(
				AuthUtil.forAnnotations(clazz), authorizationManager);
		// 顺序就和 @PreAuthorize 的顺序保持一致 
		interceptor.setOrder(AuthorizationInterceptorsOrder.PRE_AUTHORIZE.getOrder());
		return interceptor;
	}

}
